package ch3.LoadBalanceModule;

import java.util.Random;
import java.util.logging.Logger;

/**
 * 负载均衡抽象类
 */

public abstract class AbstractLoadBalancer implements LoadBalancer{
    private final static Logger LOGGER = Logger.getAnonymousLogger();
    // 使用volatile变量替代锁
    protected volatile Candidate candidate;
    private final Random random;
    // 心跳线程
    private Thread heartbeatThread;

    public AbstractLoadBalancer(Candidate candidate) {
        if (null == candidate || 0 == candidate.getEndpointCount()) {
            throw new IllegalArgumentException("Invalid candidates " + candidate);
        }
        this.candidate = candidate;
        random = new Random();
    }

    public synchronized void init() throws Exception {
        if (null == heartbeatThread) {
            heartbeatThread = new Thread(new HeartbeatTask(), "LB_Heartbeat");
            heartbeatThread.setDaemon(true);
            heartbeatThread.start();
        }
    }


    @Override
    public void updateCandidate(Candidate candidate) {
        if (null == candidate || 0 == candidate.getEndpointCount()) {
            throw new IllegalArgumentException("Invalid candidates " + candidate);
        }
        // 更新volatile变量candidata
        this.candidate = candidate;
    }

    // 留给子类实现的抽象方法
    @Override
    public abstract Endpoint nextEndpoint();

    protected void monitorEndpoints() {
       final Candidate currCandidate = candidate;
       boolean isTHeEndpointOnline;

       // 检测下游部件是否状态正常
        for (Endpoint endpoint : currCandidate.getEndpoints()) {
           isTHeEndpointOnline = endpoint.getOnline();
           if (doDetect(endpoint) != isTHeEndpointOnline) {
               endpoint.setOnline(!isTHeEndpointOnline);
           }
        }
    }

    // 检测指定的节点是否在线
    private boolean doDetect(Endpoint endpoint) {
        // ...
        return true;
    }

    private class HeartbeatTask implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    // 检测节点列表中的所有节点是否在线
                    monitorEndpoints();
                    Thread.sleep(2000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

